#include  "Typedef.h"
#include  "macros.h"

#include  "hal_uart.h"

#include  "Timer.h"
#include  "Phy_Frame.h"
#include  "Wirelessprotocol.h"
#include  "eSeal_Management.h"

#include  "stdlib.h"
#include  "string.h"



#define  ESEAL_DATA_TYPE_NONE           (0x00)


static ESEAL_DETAIL        eSeal;
static ESEAL_DATA          eSealDataTable[ESEAL_DATA_TABLE_SIZE];

//static ESEAL_DETAIL*  peSealFreeList = NULL;
static ESEAL_DATA*    peSealDataFreeList = NULL;

void eSeal_Init(void);
/*
void   eSealTable_Init(void);
INT8U  eSealTable_Free_eSealObj(INT8U* peSealID , INT8U* pVendorID);
INT8U  eSealTable_Add_eSealObj(INT8U* peSealID , INT8U* pVendorID , INT16U eSealStatus , INT8S Rssi);
INT8U  eSealTable_Update_eSealObj(INT8U* peSealID , INT8U* pVendorID , INT16U eSealStatus , INT8S Rssi);
ESEAL_DETAIL*  eSealTable_Get_eSealObj(void);
ESEAL_DETAIL*  eSealTable_Find_eSealObj(INT8U* peSealID , INT8U* pVendorID);
*/
BOOL eSeal_Check_eSealObjID(INT8U* peSealID , INT8U* pVendorID);
void eSeal_New_eSealObj(INT8U* peSealID , INT8U* pVendorID , INT16U eSealStatus, INT8S Rssi);
void eSeal_Del_eSealObj(ESEAL_DETAIL* peSeal);
void  eSeal_Update_eSealObj(ESEAL_DETAIL* peSeal , INT16U eSealStatus, INT8S Rssi);
ESEAL_DETAIL* eSeal_Get_eSealObj(void);

void   eSealDataTable_Init(void);
ESEAL_DATA*  eSealDataTable_Get_DataObj(ESEAL_DETAIL* peSeal);
ESEAL_DATA*  eSealDataTable_Del_OneDataObj(ESEAL_DETAIL* peSeal);
void   eSealData_Del_AllDataObj(ESEAL_DETAIL* peSeal);
INT8U  eSealDataTable_Add_DataObj(ESEAL_DETAIL* peSeal , INT16U DataType, INT8U DataLth, INT8U* pData);
INT8U  eSealDataTable_Get_OneDataObj(ESEAL_DETAIL* peSeal , ESEAL_DATA* peSealData);

//----------------------------------------------------------------------------------
//  void  eSeal_Init(void)
//
//  DESCRIPTION:
//    Initialize the eSealTable, fill the eSealTable member with zero and initialize
//    the free list.
//
//  ARGUMENTS:
//    None
//
//  RETURNS:
//    None
//----------------------------------------------------------------------------------
void  eSeal_Init(void)
{
    memset((INT8U* )(&eSeal) , 0 , sizeof(eSeal));
}

//----------------------------------------------------------------------------------
//  void  eSealDataTable_Init(void)
//
//  DESCRIPTION:
//    Initialize the eSealDataTable, fill the eSealDataTable member with zero and initialize
//    the free list.
//
//  ARGUMENTS:
//    None
//
//  RETURNS:
//    None
//----------------------------------------------------------------------------------
void  eSealDataTable_Init(void)
{
    INT8U  i;
    ESEAL_DATA*    peSealDataNext;

    peSealDataFreeList = &eSealDataTable[0];
    peSealDataNext = peSealDataFreeList;

    for (i = 0 ; i < ESEAL_DATA_TABLE_SIZE ; i++)
    {
        eSealDataTable[i].eSealDataLth = 0;
        eSealDataTable[i].eSealDataType = ESEAL_DATA_TYPE_NONE; 
        eSealDataTable[i].peSealData = NULL;
        
        peSealDataNext->pNextData = &eSealDataTable[i];
        peSealDataNext = peSealDataNext->pNextData;
    }
    peSealDataNext->pNextData =  NULL;
} 

//----------------------------------------------------------------------------------
//  void eSealManage_Init(void)
//
//  DESCRIPTION:
//    Initialize the eSeal management.
//      1.Initialize the eSealTable;
//      2.Initialize the eSealDataTable;
//      3.Apply the eSeal TTL Timer.
//  ARGUMENTS:
//    None
//
//  RETURNS:
//    None
//----------------------------------------------------------------------------------
void eSealManage_Init(void)
{
    eSeal_Init();
    eSealDataTable_Init();
}

BOOL eSeal_Check_eSealObjID(INT8U* peSealID , INT8U* pVendorID)
{
    if ((memcmp(peSealID,eSeal.eSealID , FRAME_DATA_LTH_ESEALID) == 0)
      &&(memcmp(pVendorID , eSeal.VendorID , FRAME_DATA_LTH_VENDORID) == 0))
    {
        return  TRUE;
    }
    else
        return  FALSE;
}

void eSeal_New_eSealObj(INT8U* peSealID , INT8U* pVendorID , INT16U eSealStatus, INT8S Rssi)
{
    memcpy(eSeal.eSealID , peSealID , FRAME_DATA_LTH_ESEALID);
    memcpy(eSeal.VendorID , pVendorID , FRAME_DATA_LTH_VENDORID);
    eSeal.eSealStatus = eSealStatus;
    eSeal.DynamicRSSI = Rssi;
}

void eSeal_Del_eSealObj(ESEAL_DETAIL* peSeal)
{
  eSealData_Del_AllDataObj(peSeal);  
  memset((INT8U* )(peSeal) , 0 , sizeof(ESEAL_DETAIL));
}

ESEAL_DETAIL* eSeal_Get_eSealObj(void)
{
    return &eSeal;
}

void  eSeal_Update_eSealObj(ESEAL_DETAIL* peSeal , INT16U eSealStatus, INT8S Rssi)
{
    peSeal->eSealStatus = eSealStatus;
    peSeal->DynamicRSSI = Rssi;
}

ESEAL_DATA* eSealDataTable_Get_DataObj(ESEAL_DETAIL* peSeal)
{
    ESEAL_DATA* pTempeData;

    ASSERT(peSeal);
        
    if (peSealDataFreeList)
    {
        pTempeData =peSealDataFreeList;
        peSealDataFreeList = peSealDataFreeList->pNextData;
        
        if (peSeal->pDataHeader)
        {
            pTempeData->pNextData = peSeal->pDataHeader;
            peSeal->pDataHeader = pTempeData;
        }
        else
        {
            
            peSeal->pDataHeader = pTempeData;
            pTempeData->pNextData = NULL;
        }
        return  pTempeData;
    }
    else
    {
        return  NULL;
    }
}
 

INT8U  eSealDataTable_Add_DataObj(ESEAL_DETAIL* peSeal , INT16U DataType, INT8U DataLth, INT8U* pData)
{
    ASSERT(peSeal);
    ASSERT(pData);

    ESEAL_DATA*  pTempData;
    
    pTempData = eSealDataTable_Get_DataObj(peSeal);

    if (pTempData)
    {
        pTempData->peSealData = (INT8U*)malloc(DataLth);

        if(pTempData->peSealData)
        {
            pTempData->eSealDataType = DataType;       
            pTempData->eSealDataLth = DataLth;
            memcpy(pTempData->peSealData , pData ,  DataLth);

            return  ESEAL_DATATABLE_NO_ERR;
        }
        else
        {
            return  ESEAL_DATATABLE_ERR;
        }
    }
    else
    {
        return  ESEAL_DATATABLE_ERR;
    }
}


INT8U  eSealDataTable_Get_OneDataObj(ESEAL_DETAIL* peSeal , ESEAL_DATA* peSealData)
{
    ESEAL_DATA*  pTempData;

    ASSERT(peSeal);
    ASSERT(peSealData);

    if (peSeal->pDataHeader)
    {
        pTempData = peSeal->pDataHeader;
        peSeal->pDataHeader = pTempData->pNextData;

        pTempData->pNextData = NULL;

        memcpy((INT8U*)(peSealData) , (INT8U*)(pTempData) , sizeof(ESEAL_DATA));

        if (peSealData->peSealData)
        {
            free(peSealData->peSealData);
        } 
        
        pTempData->pNextData = peSealDataFreeList;
        peSealDataFreeList = pTempData;

        return  ESEAL_DATATABLE_NO_ERR;
    }
    else
    {
        return  ESEAL_DATATABLE_ERR;
    }
}


ESEAL_DATA*  eSealDataTable_Find_TypeData(ESEAL_DETAIL* peSeal , INT16U  DataType)
{
    ESEAL_DATA*  pTempData;

    ASSERT(peSeal);

    pTempData = NULL;

    pTempData = peSeal->pDataHeader;
    if (peSeal->pDataHeader)
    {
       while(pTempData)        
       {
          if (pTempData->eSealDataType == DataType)
          {
              break;
          }
          pTempData = pTempData->pNextData;
       }
    }
    return pTempData;
}

void  eSealDataTable_Read_TypeData(ESEAL_DATA* pDsteSealData , ESEAL_DATA* pScreSealData)
{
    ASSERT(pDsteSealData);
    ASSERT(pScreSealData);

    memcpy((INT8U*)(pDsteSealData) , (INT8U*)(pScreSealData) , sizeof(ESEAL_DATA));
}

INT8U  eSealDataTable_Del_TypeData(ESEAL_DETAIL* peSeal , ESEAL_DATA* peSealData)
{
    ESEAL_DATA*  pTempData;
    ESEAL_DATA*  pPrevData;

    ASSERT(peSeal);
    ASSERT(peSealData);
    
    pTempData = peSeal->pDataHeader;
    pPrevData = peSeal->pDataHeader;

    if (peSealData->peSealData)
    {
        free(peSealData->peSealData);
    }

    if (peSealData == peSeal->pDataHeader)
    {
        peSeal->pDataHeader = peSealData->pNextData;
        return ESEAL_DATATABLE_NO_ERR;
    }
    else
    {
        while (pTempData)
        {
            if (pTempData == peSealData)
            {
                break;
            }
            pPrevData = pTempData;
            pTempData = pTempData->pNextData;
        }
        if (pTempData == NULL)
        {
            return  ESEAL_DATATABLE_ERR_NOT_FIND;
        }
        else
        {
            pPrevData->pNextData = pTempData->pNextData;
            return ESEAL_DATATABLE_NO_ERR;
        }

    }
}


ESEAL_DATA*  eSealDataTable_Del_OneDataObj(ESEAL_DETAIL* peSeal)
{
    ESEAL_DATA*  pTempData;

    ASSERT(peSeal);

    if (peSeal->pDataHeader)
    {
        pTempData = peSeal->pDataHeader;
        peSeal->pDataHeader = pTempData->pNextData;
        

        if (pTempData->peSealData)
        {
            free(pTempData->peSealData);
        } 

        pTempData->pNextData = peSealDataFreeList;
        peSealDataFreeList = pTempData;

        return  pTempData;
    }
    else
    {
        return  NULL;
    }
}

void  eSealData_Del_AllDataObj(ESEAL_DETAIL* peSeal)
{
    ESEAL_DATA*  pTempData;
    ESEAL_DATA*  pTempData2;
    
    ASSERT(peSeal);
    
    pTempData = peSeal->pDataHeader;

    while (pTempData)
    {
        pTempData->eSealDataLth = 0;
        pTempData->eSealDataType = 0;

        if (pTempData->peSealData)
        {
            free(pTempData->peSealData);
        }
        pTempData->peSealData = NULL;
        
        pTempData2 = pTempData->pNextData;
        
        pTempData->pNextData = peSealDataFreeList;
        peSealDataFreeList = pTempData;

        pTempData = pTempData2;
    
    }

}

void  eSealDataTable_Update_DataObj(ESEAL_DATA* peSealData , INT8U DataLth, INT8U* pData)
{
    ASSERT(peSealData);

    if (DataLth != peSealData->eSealDataLth)
    {
        if (peSealData->peSealData)
        {
            free(peSealData->peSealData);
            peSealData->peSealData = (INT8U*)malloc(DataLth);
            if (peSealData->peSealData)
            {
                memcpy(peSealData->peSealData , pData , DataLth);
            }
        }       
    }
    else
        memcpy(peSealData->peSealData , pData , DataLth);
}